/***************************************************************************
 * Name:
 *     sm712.c
 * License:
 *     2003-2007, Copyright by BLX IC Design Co., Ltd.
 * Description:
 *     sm712 driver
 *
 ***************************************************************************/
#include "types.h"
#include "sm712.h"
#include "pci_machdep.h"

static  UINT8   *SMIRegs;        /* point to virtual Memory Map IO starting address */
static  UINT8   *SMILFB;         /* point to virtual video memory starting address  */
static  struct par_info hw;     /* used to record hardware information             */
UINT8 smi_2d_busy = 0;
UINT8 *SMI2DBaseAddress;



struct ModeInit VGAMode[numVGAModes] =
{
	{
		/*  mode#0: 640 x 480  8Bpp  60Hz */
		640, 480, 8, 60,
		/*  Init_MISC */
		0xE3,
		{   /*  Init_SR0_SR4 */
			0x03, 0x01, 0x0F, 0x00, 0x0E,
		},
		{   /*  Init_SR10_SR24 */
			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xC4, 0x30, 0x02, 0x01, 0x01,
		},
		{   /*  Init_SR30_SR75 */
			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
		},
		{   /*  Init_SR80_SR93 */
			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
			0x00, 0x00, 0x00, 0x00,
		},
		{   /*  Init_SRA0_SRAF */
			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
		},
		{   /*  Init_GR00_GR08 */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
			0xFF,
		},
		{   /*  Init_AR00_AR14 */
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
			0x41, 0x00, 0x0F, 0x00, 0x00,
		},
		{   /*  Init_CR00_CR18 */
			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
			0xFF,
		},
		{   /*  Init_CR30_CR4D */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
		},
		{   /*  Init_CR90_CRA7 */
			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
		},
	},

	{
		/*  mode#1: 640 x 480  16Bpp  60Hz */
		640, 480, 16, 60,
		/*  Init_MISC */
		0xE3,
		{   /*  Init_SR0_SR4 */
			0x03, 0x01, 0x0F, 0x00, 0x0E,
		},
		{   /*  Init_SR10_SR24 */
			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xC4, 0x30, 0x02, 0x01, 0x01,
		},
		{   /*  Init_SR30_SR75 */
			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
		},
		{   /*  Init_SR80_SR93 */
			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
			0x00, 0x00, 0x00, 0x00,
		},
		{   /*  Init_SRA0_SRAF */
			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
		},
		{   /*  Init_GR00_GR08 */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
			0xFF,
		},
		{   /*  Init_AR00_AR14 */
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
			0x41, 0x00, 0x0F, 0x00, 0x00,
		},
		{   /*  Init_CR00_CR18 */
			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
			0xFF,
		},
		{   /*  Init_CR30_CR4D */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
		},
		{   /*  Init_CR90_CRA7 */
			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
		},
	},
	{
		/*  mode#2: 640 x 480  24Bpp  60Hz */
		640, 480, 24, 60,
		/*  Init_MISC */
		0xE3,
		{   /*  Init_SR0_SR4 */
			0x03, 0x01, 0x0F, 0x00, 0x0E,
		},
		{   /*  Init_SR10_SR24 */
			0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xC4, 0x30, 0x02, 0x01, 0x01,
		},
		{   /*  Init_SR30_SR75 */
			0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32,
			0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF,
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32,
			0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA,
			0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32,
			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
			0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04,
			0x00, 0x45, 0x30, 0x30, 0x40, 0x30,
		},
		{   /*  Init_SR80_SR93 */
			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32,
			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32,
			0x00, 0x00, 0x00, 0x00,
		},
		{   /*  Init_SRA0_SRAF */
			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF,
		},
		{   /*  Init_GR00_GR08 */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
			0xFF,
		},
		{   /*  Init_AR00_AR14 */
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
			0x41, 0x00, 0x0F, 0x00, 0x00,
		},
		{   /*  Init_CR00_CR18 */
			0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E,
			0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3,
			0xFF,
		},
		{   /*  Init_CR30_CR4D */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20,
			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD,
			0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
			0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF,
		},
		{   /*  Init_CR90_CRA7 */
			0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55,
			0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00,
			0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00,
		},
	},
	{/*  mode#3: 800 x 600  8Bpp  60Hz */
		800,600,8,60,
		0x2B,   /*  Init_MISC */
		{       /*  Init_SR0_SR4 */
			0x03, 0x01, 0x0F, 0x03, 0x0E,
		},
		{   /*  Init_SR10_SR24 */
			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
			0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xC4, 0x30, 0x02, 0x01, 0x01,
		},
		{   /*  Init_SR30_SR75 */
			0x24, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
			0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
			0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
			0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
		},
		{   /*  Init_SR80_SR93 */
			0xFF, 0x87, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
			0x90, 0x01, 0x2C, 0x01, 0xFF, 0x00, 0x24, 0x24,
			0x00, 0x00, 0x00, 0x00,
		},
		{   /*  Init_SRA0_SRAF */
			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
		},
		{   /*  Init_GR00_GR08 */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
			0xFF,
		},
		{   /*  Init_AR00_AR14 */
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
			0x41, 0x00, 0x0F, 0x00, 0x00,
		},
		{   /*  Init_CR00_CR18 */
			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
			0xFF,
		},
		{   /*  Init_CR30_CR4D */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
		},
		{   /*  Init_CR90_CRA7 */
			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
		},
	},
	{/*  mode#4: 800 x 600  16Bpp  60Hz */
		800, 600, 16, 60,
		/*  Init_MISC */
		0x2B,
		{   /*  Init_SR0_SR4 */
			0x03, 0x01, 0x0F, 0x03, 0x0E,
		},
		{   /*  Init_SR10_SR24 */
			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
			0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xC4, 0x30, 0x02, 0x01, 0x01,
		},
		{   /*  Init_SR30_SR75 */
			0x24, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24,
			0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF,
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC,
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24,
			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
			0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24,
			0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00,
			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
			0x02, 0x45, 0x30, 0x35, 0x40, 0x20,
		},
		{   /*  Init_SR80_SR93 */
			0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24,
			0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24,
			0x00, 0x00, 0x00, 0x00,
		},
		{   /*  Init_SRA0_SRAF */
			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
		},
		{   /*  Init_GR00_GR08 */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
			0xFF,
		},
		{   /*  Init_AR00_AR14 */
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
			0x41, 0x00, 0x0F, 0x00, 0x00,
		},
		{   /*  Init_CR00_CR18 */
			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
			0xFF,
		},
		{   /*  Init_CR30_CR4D */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,

			//0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
			//0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
		},
		{   /*  Init_CR90_CRA7 */
			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
		},
	},
	{/*  mode#5: 800 x 600  24Bpp  60Hz */
		800,600,24,60,
		0x2B,
		{   /*  Init_SR0_SR4 */
			0x03, 0x01, 0x0F, 0x03, 0x0E,
		},
		{   /*  Init_SR10_SR24 */
			0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C,
			0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0xC4, 0x30, 0x02, 0x01, 0x01,
		},
		{   /*  Init_SR30_SR75 */
			0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36,
			0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF,
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36,
			0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58,
			0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36,
			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
			0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13,
			0x02, 0x45, 0x30, 0x30, 0x40, 0x20,
		},
		{   /*  Init_SR80_SR93 */
			0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36,
			0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36,
			0x00, 0x00, 0x00, 0x00,
		},
		{   /*  Init_SRA0_SRAF */
			0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED,
			0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF,
		},
		{   /*  Init_GR00_GR08 */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
			0xFF,
		},
		{   /*  Init_AR00_AR14 */
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
			0x41, 0x00, 0x0F, 0x00, 0x00,
		},
		{   /*  Init_CR00_CR18 */
			0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0,
			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
			0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3,
			0xFF,
		},
		{   /*  Init_CR30_CR4D */
			0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20,
			0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD,
			0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
			0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57,
		},
		{   /*  Init_CR90_CRA7 */
			0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA,
			0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00,
			0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00,
		},
	},
    { /*  mode#6: 1024 x 600  16Bpp  60Hz */ 
        1024,600,16,60,
		/*  Init_MISC */                                    
		0xEB,                                               
		{   /*  Init_SR0_SR4 */                             
			0x03, 0x01, 0x0F, 0x00, 0x0E,                   
		},                                                  
		{   /*  Init_SR10_SR24 */                           
			0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x92, 0x00, 
			0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
			0xC4, 0x30, 0x02, 0x00, 0x01,                   
		},                                                  
		{   /*  Init_SR30_SR75 */                           
			0x28, 0x03, 0x24, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, 
			0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, 
			0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 
			0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, 
			0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, 
			0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, 
			0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 
			0x50, 0x03, 0x16, 0x02, 0x52, 0x89, 0x09, 0x02, 
			0x04, 0x45, 0x30, 0x30, 0x40, 0x20,             
		},                                                  
		{   /*  Init_SR80_SR93 */                           
			0xFF, 0x07, 0x00, 0x00, 0x08, 0x00, 0x42, 0x3A, 
			0x59, 0x02, 0x44, 0x02, 0x00, 0xFF, 0x3A, 0x3A, 
			0x00, 0x00, 0x00, 0x00,                         
		},                                                  
		{   /*  Init_SRA0_SRAF */                           
			0x00, 0x10, 0x08, 0x00, 0x02, 0xED, 0xED, 0xED, 
			0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, 
		},                                                  
		{   /*  Init_GR00_GR08 */                           
			0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 
			0xFF,                                           
		},                                                  
		{   /*  Init_AR00_AR14 */                           
			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 
			0x41, 0x00, 0x0F, 0x00, 0x00,                   
		},                                                  
		{   /*  Init_CR00_CR18 */                           
			0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, 
			0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
			0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, 
			0xFF,                                           
		},                                                  
		{   /*  Init_CR30_CR4D */                           
			0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 
			0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0x46, 0x91, 
			0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, 
			0x01, 0x07, 0xE5, 0x20, 0x7F, 0x57,             

		},                                                  
		{   /*  Init_CR90_CRA7 */                           
			0x55, 0xD5, 0x5D, 0xDD, 0x86, 0x17, 0x8E, 0xAA, 
			0x8A, 0xA3, 0xDE, 0xAB, 0x00, 0x00, 0x00, 0x00, 
			0x02, 0x02, 0x02, 0x15, 0x02, 0x06, 0x00, 0x00, 
		},                                                  
	},                                                      
};


static inline void smi_crtcw(int reg, int val)
{
	smi_mmiowb(reg, 0x3d4);
	smi_mmiowb(val, 0x3d5);
}

static inline UINTN smi_crtcr(int reg)
{       
	smi_mmiowb(reg, 0x3d4);
	return smi_mmiorb(0x3d5);
}

static inline void smi_grphw(int reg, int val)
{
	smi_mmiowb(reg, 0x3ce);
	smi_mmiowb(val, 0x3cf);
}

static inline UINTN smi_grphr(int reg)
{
	smi_mmiowb(reg, 0x3ce);
	return smi_mmiorb(0x3cf);
}

static inline void smi_attrw(int reg, int val)
{
	smi_mmiorb(0x3da);
	smi_mmiowb(reg, 0x3c0);
	smi_mmiorb(0x3c1);
	smi_mmiowb(val, 0x3c0);
}

static inline void smi_seqw(int reg, int val)
{
	smi_mmiowb(reg, 0x3c4);
	smi_mmiowb(val, 0x3c5);
}

static inline UINTN smi_seqr(int reg)
{
	smi_mmiowb(reg, 0x3c4);
	return smi_mmiorb(0x3c5);
}


void smi_2dregw(UINTN offset, UINTN data)
{
	*((volatile UINTN*)(SMI2DBaseAddress + offset)) = data;
}

UINTN smi_2dregr(UINTN offset)
{
	return *((volatile UINTN*)(SMI2DBaseAddress + offset));
}



/*******************************SM712 2D Engine*******************************/

#ifdef	SM712_2D_DEBUG
void smi_2d_wait_for_nonbusy(void)
{
	UINTN i = 0x100000;

	while(i--){
		if( (smi_seqr(0x16) & 0x18) == 0x10 ){
			break;
		}
	}

	smi_2d_busy = 0;
}

void sm712_2d_init(void)
{
	/* 
	 * crop top boundary
	 * crop disable
	 * crop inhibit outside
	 * crop left boundary
	 */
	smi_2dregw( REG_2D_CROP_LEFTTOP, (0x000 << 16) | (0 << 13) | (0 << 12) | (0x000 << 0) );
	smi_2dregw( REG_2D_CROP_RIGHTBOTTOM, (SM712_FIX_HEIGHT << 16) | (SM712_FIX_WIDTH << 0) );
	/*
	 * pitch src/dst width in pixel 
	 * window src/dst width in pixel
	 */
	smi_2dregw( REG_2D_PITCH_XY, (SM712_FIX_WIDTH << 16) | (SM712_FIX_WIDTH << 0) );
	smi_2dregw( REG_2D_SRC_WINDOW, (SM712_FIX_WIDTH << 16) | (SM712_FIX_WIDTH << 0) );
	/*
	 * normal drawing engine
	 * pattern y
	 * pattern x
	 * 16bpp
	 * xy mode
	 * stretch height Y
	 */
	smi_2dregw( REG_2D_DEDF, (1 << 30) | (0x00 << 27) | (0x00 << 24) | 
					(0x01 << 20) | (0x00 << 16) | (0x03 << 0) );
	/*
	 * byte mask
	 * bit mask
	 */
	smi_2dregw( REG_2D_BB_MASK, (0xffff << 16) | (0xffff << 0) );
	/*
	 * color compare mask
	 */
	smi_2dregw( REG_2D_COLOR_COM_MASK, (0xffffff << 0) );
	/*
	 * color compare
	 */
	smi_2dregw( REG_2D_COLOR_COM, (0xffffff << 0) );
}

void sm712_2d_copy(UINTN dst_base, UINTN dst_bpp, 
				UINTN dst_x, UINTN dst_y, 
				UINTN dst_w, UINTN dst_h, 
				UINTN src_base, UINTN src_x, 
				UINTN src_y, UINTN rop2)
{
	UINTN nDirection = 0;

	smi_2d_wait_for_nonbusy();

	smi_2dregw( REG_2D_SRC_BASE, (src_base << 0) );
	smi_2dregw( REG_2D_DST_BASE, (dst_base << 0) );
	if(src_y < dst_y){
		nDirection = 1;
	}else if(src_y > dst_y){
		nDirection = 0;
	}else{
		if(src_x <= dst_x){
			nDirection = 1;
		}else{
			nDirection = 0;
		}
	}
	if( nDirection == 1 ){
		src_x += dst_w - 1;
		dst_x += dst_w - 1;
		src_y += dst_h - 1;
		dst_y += dst_h - 1;
	}

	smi_2dregw( REG_2D_SRC_XY, (0 << 31) | (src_x << 16) | (src_y << 0) );
	smi_2dregw( REG_2D_DST_XY, (0 << 31) | (dst_x << 16) | (dst_y << 0) );
	smi_2dregw( REG_2D_DIM_XY, (dst_w << 16) | (dst_h << 0) );
	/*
	 * bit31 : 2d engine start
	 * bit27 : left to right/right to left
	 * bit20:16 : command bitblt
	 * bit15 : rop2
	 * bit3:0 : rop code(just source)
	 */
	smi_2dregw( REG_2D_DE_CTRL, (1 << 31) | (nDirection << 27) | (0x0 << 16) | (1 << 15) | (0x0c << 0) );

	smi_2d_busy = 1;	
}

void video_hw_bitblt(UINTN bpp, UINTN sx, UINTN sy, UINTN dx, UINTN dy, UINTN w, UINTN h)
{
	sm712_2d_copy(0, bpp, dx, dy, w, h, 0, sx, sy, 0x0c);

	return;
}

void sm712_2d_fill_rect(UINTN dst_base, UINTN dst_x, UINTN dst_y,
			   	UINTN dst_w, UINTN dst_h, UINTN color)
{
	smi_2d_wait_for_nonbusy();
	
	smi_2dregw( REG_2D_DST_BASE, (dst_base << 0) );
	smi_2dregw( REG_2D_COLOR_FG, (color << 0) );
	smi_2dregw( REG_2D_MONO_PATTERN_LOW, 0xffffffff );
	smi_2dregw( REG_2D_MONO_PATTERN_HIGH, 0xffffffff );
	smi_2dregw( REG_2D_PITCH_XY, (SM712_FIX_WIDTH << 16) | (SM712_FIX_WIDTH << 0) );
	smi_2dregw( REG_2D_SRC_WINDOW, (SM712_FIX_WIDTH << 16) | (SM712_FIX_WIDTH << 0) );

	/*
	 * wrap disable 
	 */
	smi_2dregw( REG_2D_DST_XY, (0 << 31) | (dst_x << 16) | (dst_y << 0) );
	smi_2dregw( REG_2D_DIM_XY, (dst_w << 16) | (dst_h << 0) );
	/*
	 * bit31 : 2d engine start
	 * bit27 : left to right
	 * bit21 : draw last pixel
	 * bit20:16 : command rectangle fill
	 * bit15 : rop2
	 * bit3:0 : rop code(just source)
	 */
	smi_2dregw( REG_2D_DE_CTRL, (1 << 31) | (0 << 27) | (0 << 21) 
					| (0x1 << 16) | (1 << 15) | (0x0c << 0) );
	if( (pci_io_read8( 0x3cc)) & 0x01 ){
		while( (pci_io_read8( 0x3da)) & 0x08 );
		while( !((pci_io_read8( 0x3da)) & 0x08) );
	}else{
		while( (pci_io_read8( 0x3ba)) & 0x08 );
		while( !((pci_io_read8( 0x3ba)) & 0x08) );
	}

	smi_2d_busy = 1;	
}

void video_hw_rectfill(UINTN bpp, UINTN dst_x, UINTN dst_y, 
				UINTN dim_x, UINTN dim_y, UINTN color)
{
	sm712_2d_fill_rect(0, dst_x, dst_y, dim_x, dim_y, color);

	return;
}

#endif	/* SM712_2D_DEBUG */

/*****************************************************************************/

static void smi_set_timing(struct par_info *hw)
{
	int i=0,j=0;
	UINT32 m_nScreenStride;
	
	for (j=0;j < numVGAModes;j++) {
		if (VGAMode[j].mmSizeX == hw->width &&
				VGAMode[j].mmSizeY == hw->height &&
				VGAMode[j].bpp == hw->bits_per_pixel &&
				VGAMode[j].hz == hw->hz)
		{
			smi_mmiowb(0x0,0x3c6);

			smi_seqw(0,0x1);

			smi_mmiowb(VGAMode[j].Init_MISC,0x3c2);

			for (i=0;i<SIZE_SR00_SR04;i++)  /* init SEQ register SR00 - SR04 */
			{
				smi_seqw(i,VGAMode[j].Init_SR00_SR04[i]);
			}

			for (i=0;i<SIZE_SR10_SR24;i++)  /* init SEQ register SR10 - SR24 */
			{
				smi_seqw(i+0x10,VGAMode[j].Init_SR10_SR24[i]);
			}

			for (i=0;i<SIZE_SR30_SR75;i++)  /* init SEQ register SR30 - SR75 */
			{
				if (((i+0x30) != 0x62) && ((i+0x30) != 0x6a) && ((i+0x30) != 0x6b))
					smi_seqw(i+0x30,VGAMode[j].Init_SR30_SR75[i]);
			}
			for (i=0;i<SIZE_SR80_SR93;i++)  /* init SEQ register SR80 - SR93 */
			{
				smi_seqw(i+0x80,VGAMode[j].Init_SR80_SR93[i]);
			}
			for (i=0;i<SIZE_SRA0_SRAF;i++)  /* init SEQ register SRA0 - SRAF */
			{
				smi_seqw(i+0xa0,VGAMode[j].Init_SRA0_SRAF[i]);
			}

			for (i=0;i<SIZE_GR00_GR08;i++)  /* init Graphic register GR00 - GR08 */
			{
				smi_grphw(i,VGAMode[j].Init_GR00_GR08[i]);
			}

			for (i=0;i<SIZE_AR00_AR14;i++)  /* init Attribute register AR00 - AR14 */
			{

				smi_attrw(i,VGAMode[j].Init_AR00_AR14[i]);
			}

			for (i=0;i<SIZE_CR00_CR18;i++)  /* init CRTC register CR00 - CR18 */
			{
				smi_crtcw(i,VGAMode[j].Init_CR00_CR18[i]);
			}

			for (i=0;i<SIZE_CR30_CR4D;i++)  /* init CRTC register CR30 - CR4D */
			{
				smi_crtcw(i+0x30,VGAMode[j].Init_CR30_CR4D[i]);
			}

			for (i=0;i<SIZE_CR90_CRA7;i++)  /* init CRTC register CR90 - CRA7 */
			{
				smi_crtcw(i+0x90,VGAMode[j].Init_CR90_CRA7[i]);
			}
		}
	}
	smi_mmiowb(0x67,0x3c2);

	/* set VPR registers */
	smi_mmiowl(hw->m_pVPR+0x0C, 0x0);
	smi_mmiowl(hw->m_pVPR+0x40, 0x0);
	/* set data width */
	m_nScreenStride = (hw->width * hw->bits_per_pixel) / 64;

	/* case 16: */
	smi_mmiowl(hw->m_pVPR+0x0, 0x00020000);

	smi_mmiowl(hw->m_pVPR+0x10, (UINT32)(((m_nScreenStride + 2) << 16) | m_nScreenStride));
}



/***************************************************************************
 * We need to wake up the LynxEM+, and make sure its in linear memory mode.
 ***************************************************************************/
static inline void smi_init_hw(void)
{
	pci_io_write8(0x18, 0x3c4);
	pci_io_write8(0x11, 0x3c5);
}

int  sm712_init(UINT8 * fbaddress,UINT8 * ioaddress)
{
	
	UINT32 smem_size, i;
	
	smi_init_hw();
	
	hw.m_pLFB = SMILFB = fbaddress;
	hw.m_pMMIO = SMIRegs = SMILFB + 0x00700000; /* ioaddress */
	hw.m_pDPR = hw.m_pLFB + 0x00408000;
	hw.m_pVPR = hw.m_pLFB + 0x0040c000;

	/* now we fix the  mode */
	hw.width = SM712_FIX_WIDTH;
	hw.height = SM712_FIX_HEIGHT;
	hw.bits_per_pixel = SM712_FIX_DEPTH;
	hw.hz = SM712_FIX_HZ;

	if (!SMIRegs)
	{
		return -1;
	}

	smi_seqw(0x21,0x00); 
	
	smi_seqw(0x62,0x7A);
	smi_seqw(0x6a,0x16);
	smi_seqw(0x6b,0x02);
	
	smem_size = 0x00400000;
	for(i = 0; i  < smem_size / 2; i += 4){
		*((volatile UINTN*)(fbaddress + i)) = 0x00;
	}

	/* LynxEM+ memory dection */
	*(UINT32 *)(SMILFB + 4) = 0xAA551133;
	if (*(UINT32 *)(SMILFB + 4) != 0xAA551133)
	{
		smem_size = 0x00200000;
		/* Program the MCLK to 130 MHz */
		smi_seqw(0x6a,0x12);
		smi_seqw(0x6b,0x02);
		smi_seqw(0x62,0x3e);
	}

	smi_set_timing(&hw);

#ifdef	SM712_2D_DEBUG
	SMI2DBaseAddress = hw.m_pDPR;
	sm712_2d_init();
#endif


	return 0;
}



int GetXRes(void)
{
	return SM712_FIX_WIDTH;
}

int GetYRes(void)
{
	return SM712_FIX_HEIGHT;
}

int GetBytesPP(void)
{
	return (SM712_FIX_DEPTH / 8);
}

